﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using EnvDTE;
using System.IO;
using EnvDTE80;
using System.Collections;
using SPVisualDev.VSAddin.Dialogs;

namespace SPVisualDev.VSAddin.Dialogs
{
    internal partial class DialogSNKSelector : Form
    {
        private Project m_startup_project;

        public DialogSNKSelector(Project project)
        {
            InitializeComponent();

            m_startup_project = project;

            this.Load += new EventHandler(DialogCodeFileSelector_Load);
        }

        private void DialogCodeFileSelector_Load(object sender, EventArgs e)
        {
            ProjectExplorer.Initialize(m_startup_project);
            ProjectExplorer.ShowFiles = true;
            ProjectExplorer.ShowFolders = true;
            ProjectExplorer.RenderRootNode();

            if (ProjectExplorer.TreeView.TopNode != null)
            {
                ProjectExplorer.TreeView.SelectedNode = ProjectExplorer.TreeView.TopNode;
                ProjectExplorer.TreeView.Refresh();
                ProjectExplorer.TreeView.Focus();
            }
        }


        private ProjectItems GetSelectedFolder(bool showErrors, bool onlyFoldersSelect)
        {
            if (ProjectExplorer.TreeView == null)
            {
                if (showErrors)
                    ShowErrorMessage();

                ProjectExplorer.TreeView.Focus();
                return null;
            }

            if (ProjectExplorer.TreeView.SelectedNode == null)
            {
                if (showErrors)
                    ShowErrorMessage();

                ProjectExplorer.TreeView.Focus();
                return null;
            }

            ProjectItem selected_item = ProjectExplorer.TreeView.SelectedNode.Tag as ProjectItem;
            ProjectItems items_collection = null;

            if (selected_item != null)
            {
                if (selected_item.Kind != Constants.vsProjectItemKindPhysicalFolder && onlyFoldersSelect)
                {
                    items_collection = null;
                }
                else 
                {
                    if (selected_item.Kind == Constants.vsProjectItemKindPhysicalFolder)
                    {
                        items_collection = selected_item.ProjectItems;
                    }
                    else
                    {
                        items_collection = selected_item.Collection;
                    }
                }
            }
            else if (ProjectExplorer.TreeView.SelectedNode.Tag is Project)
            {
                items_collection = (ProjectExplorer.TreeView.SelectedNode.Tag as Project).ProjectItems;
            }

            if (items_collection == null && showErrors)
            {
                ShowErrorMessage();
            }

            ProjectExplorer.TreeView.Focus();

            return items_collection;
        }

        private void ShowErrorMessage()
        {
            MessageBox.Show("You must select a folder where the file will be added under.", "Prompt", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }

        private void btnAddFromFile_Click(object sender, EventArgs e)
        {
            try
            {
                ImportKeyFile();
            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex);
            }

        }

        private void btnCreateFolder_Click(object sender, EventArgs e)
        {
            try
            {
                string safe_file_name;

                ProjectItems items_collection = GetSelectedFolder(true, true);
                if (items_collection == null)
                    return;

                using (DialogInputBox dialog = new DialogInputBox())
                {
                    dialog.Text = "Create folder";
                    dialog.InfoMessage = "Enter folder name";
                    DialogResult result = dialog.ShowDialog();

                    ProjectExplorer.TreeView.Focus();

                    if (result != DialogResult.OK)
                    {
                        return;
                    }

                    if (string.IsNullOrEmpty(dialog.InputText))
                        throw new Exception("Name can not be empty.");

                    safe_file_name = Common.FilterIllegalCharsInFileName(dialog.InputText);

                    ProjectItem item = items_collection.AddFolder(safe_file_name, Constants.vsProjectItemKindPhysicalFolder);

                    TreeNode node = ProjectExplorer.TreeView.SelectedNode.Nodes.Add(item.Name, item.Name);
                    node.ImageKey = "Folder";
                    node.SelectedImageKey = "Folder";
                    node.Tag = item;

                    ProjectExplorer.TreeView.Sort();

                    ProjectExplorer.TreeView.SelectedNode = node;
                    ProjectExplorer.TreeView.Focus();
                }

            }
            catch (Exception ex)
            {
                
                DialogError.ShowError(ex);
            }
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            try
            {
                ProjectItems items_collection = GetSelectedFolder(true, false);
                if (items_collection == null)
                    return;

                ProjectItem item = items_collection.Parent as ProjectItem;
                if (item == null)
                {
                    MessageBox.Show("You can't delete the project node.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }

                string msg = "Do you want to delete the item '" + Common.GetProjectItemPath(item, true) + "'?";
                if (MessageBox.Show(msg, "Prompt", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) != DialogResult.OK)
                    return;

                item.Delete();

                ProjectExplorer.TreeView.SelectedNode.Remove();
            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex);
            }


        }

        private void btnAddItemEventRec_Click(object sender, EventArgs e)
        {
            try
            {
                AddNewKeyFile();
            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex);
            }
        }

        private void AddNewKeyFile()
        {
            ProjectItems items_collection = GetSelectedFolder(true, true);
            if (items_collection == null)
                return;


            string safe_file_name;

            using (DialogInputBox dialog = new DialogInputBox())
            {
                dialog.Text = "Add new key file";
                dialog.InfoMessage = "Enter file name";

                string ext = ".snk";

                dialog.InputText = "keyfile" + ext;
                dialog.InfoMessage = "Choose a file name for the new key file. It will be created under '" + ProjectExplorer.TreeView.SelectedNode.Name + "'";
                dialog.DialogTitle = "Enter file name";

                DialogResult result = dialog.ShowDialog();

                ProjectExplorer.TreeView.Focus();

                if (result != DialogResult.OK)
                {
                    return;
                }

                if (string.IsNullOrEmpty(dialog.InputText))
                    throw new Exception("Name can not be empty.");

                safe_file_name = Common.FilterIllegalCharsInFileName(Path.GetFileNameWithoutExtension(dialog.InputText));
                safe_file_name += Path.GetExtension(dialog.InputText);


                string tmp_path = Path.GetTempPath();
                if (tmp_path.EndsWith("\\"))
                    tmp_path.Substring(0, tmp_path.Length - 1);

                string key_file_tmp = tmp_path + "\\" + safe_file_name;
                if (File.Exists(key_file_tmp))
                    File.Delete(key_file_tmp);

                string key_container_tmp = Path.GetTempFileName();

                ProjectItem key_item = null;
                try
                {
                    VSLangProj80.VSProject2 vsproj2 = (VSLangProj80.VSProject2)items_collection.ContainingProject.Object;
                    vsproj2.GenerateKeyPairFiles(key_file_tmp, key_container_tmp);

                    items_collection.AddFromFileCopy(key_file_tmp);

                    key_item = items_collection.Item(Path.GetFileName(key_file_tmp));
                }
                finally
                {
                    if (File.Exists(key_file_tmp))
                        File.Delete(key_file_tmp);

                    if (File.Exists(key_container_tmp))
                        File.Delete(key_container_tmp);
                }

                TreeNode node = ProjectExplorer.TreeView.SelectedNode.Nodes.Add(key_item.Name, key_item.Name);
                node.ImageKey = "File";
                node.SelectedImageKey = "File";
                node.Tag = key_item;

                ProjectExplorer.TreeView.Sort();

                ProjectExplorer.TreeView.SelectedNode = node;
                ProjectExplorer.TreeView.Focus();
            }

        }

        private void ImportKeyFile()
        {
            ProjectItems items_collection = GetSelectedFolder(true, true);
            if (items_collection == null)
                return;

            ProjectItem selected_item = ProjectExplorer.TreeView.SelectedNode.Tag as ProjectItem;

            DTE2 dte2 = m_startup_project.DTE as DTE2;
            string parent = m_startup_project.UniqueName.Substring(0, m_startup_project.UniqueName.IndexOf("\\"));

            string path = string.Empty;
            if (selected_item != null)
                path = Common.GetProjectItemPath(selected_item, true);

            UIHierarchyItem ui_item = dte2.ToolWindows.SolutionExplorer.GetItem(parent + "\\" + m_startup_project.Name + "\\" + path);
            ui_item.Select(vsUISelectionType.vsUISelectionTypeSelect);

            dte2.ExecuteCommand("Project.AddExistingItem", "");
            
            if (dte2.SelectedItems.Count == 0)
                return;

            ProjectItem new_item = dte2.SelectedItems.Item(1).ProjectItem as ProjectItem;
            if (new_item == null)
                return;

            new_item.Document.Close(vsSaveChanges.vsSaveChangesYes);

            TreeNode node = ProjectExplorer.TreeView.SelectedNode.Nodes.Add(new_item.Name, new_item.Name);
            node.ImageKey = "File";
            node.SelectedImageKey = "File";
            node.Tag = new_item;

            ProjectExplorer.TreeView.Sort();

            ProjectExplorer.TreeView.SelectedNode = node;
            ProjectExplorer.TreeView.Focus();

        }

        private class ItemNodeComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                ProjectItem itemX = (x as TreeNode).Tag as ProjectItem;
                ProjectItem itemY = (y as TreeNode).Tag as ProjectItem;

                if (itemX == null)
                    return -1;

                if (itemY == null)
                    return 1;

                if (itemX.Kind == Constants.vsProjectItemKindPhysicalFolder ||
                    itemX.Kind == Constants.vsProjectItemKindVirtualFolder)
                {
                    if (itemY.Kind == Constants.vsProjectItemKindPhysicalFolder ||
                        itemY.Kind == Constants.vsProjectItemKindVirtualFolder)
                        return string.Compare(itemX.Name, itemY.Name);
                    else
                        return -1;
                }
                else
                {
                    if (itemY.Kind != Constants.vsProjectItemKindPhysicalFolder &&
                        itemY.Kind != Constants.vsProjectItemKindVirtualFolder)
                        return string.Compare(itemX.Name, itemY.Name);
                    else
                        return 1;
                }
            }
        }

    }

}
